import { App, Component, VNode, createApp, createVNode } from "vue";
import { PopupRnderEvent } from "./type";
import { v4 as uuidv4 } from "uuid";
import "element-plus/dist/index.css";
let popupOpenCount = 0;
export abstract class Popup<T> {
	// 弹出层类配合渲染的组件
	private component: Component;
	// 弹出层权重
	private zIndex = 1000;
	// 容器随机id
	private containerId = uuidv4();
	// 存储的弹出层vnode
	private popups = new Map<string, { app: App<Element>; shutDown: () => void }>();
	constructor(component: Component, zIndex?: number) {
		this.component = component;
		this.createContainer();
		if (zIndex) {
			this.zIndex = zIndex;
		}
	}
	/**
	 * 打开弹出层
	 * @param options 传入的组件配置
	 * @returns
	 */
	showPopup(options: T, sign: boolean = false): PopupRnderEvent {
		if (this.popups.size > 0) {
			this.popups.forEach(e => {
				e.app.unmount();
			});
			this.popups.clear();
		}
		// 为打开的弹出层创建唯一id
		const uuid = uuidv4();

		// 定义关闭弹出层的方法
		const shutDown = () => {
			const popupDom = document.getElementById(uuid);
			if (popupDom) {
				this.remove(popupDom);
			}
		};

		addEventListener("hashchange", () => {
			const popupDom = document.getElementById(uuid);
			popupDom && this.remove(popupDom);
		});

		this.render({ ...options, ...{ shutDown } }, uuid, sign);
		popupOpenCount += 1;
		const repaint = () => {
			this.popups.get(uuid)?.app.unmount();
			this.render({ ...options, ...{ shutDown } }, uuid, false, false);
		};
		return {
			shutDown,
			repaint,
		};
	}
	/**
	 * 渲染弹出层
	 * @param options 弹出层配置
	 * @param uuid 弹出层随机id
	 */
	private render(
		options: T & { shutDown: () => void },
		uuid: string,
		sign: boolean,
		isAnimation: boolean = true
	) {
		// 创建弹出层vnode
		const vNode = createVNode(
			this.component,
			{
				...options,
				...{
					zIndex: this.zIndex + popupOpenCount,
					id: uuid,
					style: isAnimation
						? {
								// 新增淡入动画
								animation: "fadeIn .2s",
								opacity: sign ? 0 : 1,
						  }
						: {},
				},
			},
			{
				content: () => this.getContentVNode(),
				bottom: () => this.getBottomVNode(),
			}
		);

		//实例存储在map中
		const containerEl = document.getElementById(this.containerId);
		const app = createApp(vNode);
		app.mount(containerEl!);
		this.popups.set(uuid, { app, shutDown: options.shutDown });
	}
	/**
	 * 创建容器,存放popup
	 */
	private createContainer(): void {
		const div = document.createElement("div");
		div.id = this.containerId;
		document.body.appendChild(div);
	}
	/**
	 * 移除元素
	 * @param element 需要移除的元素
	 */
	private remove(element: HTMLElement): void {
		// 新增关闭淡出动画,关闭动画结束进行dom移除
		this.popups.get(element.id)?.app.unmount();
		element.style.animation = "fadeOut .2s";
		element.addEventListener("animationend", () => {
			this.popups.delete(element.id);
			popupOpenCount -= 1;
		});
	}
	/**
	 * 获取容器id,为测试提供
	 * @returns
	 */
	getContainerId(): string {
		return this.containerId;
	}
	/**
	 * 获取content插槽区域的vnode
	 */
	abstract getContentVNode(): VNode;
	/**
	 * 获取bottom插槽区域的vnode
	 */
	abstract getBottomVNode(): VNode;
}
